package com.course.gateway.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@Component
public class LoginAdminGatewayFilter implements GatewayFilter, Ordered {

    private static final Logger LOG = LoggerFactory.getLogger(LoginAdminGatewayFilter.class);

    @Resource(name = "myRedisTemplate")
    private RedisTemplate redisTemplate;

/*    @Autowired
    private HostHolder hostHolder;//todo springcloud项目的HostHolder可以实现存放当前用户的登录信息吗？*/

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String path = exchange.getRequest().getURI().getPath();

        //控台-不需要登录就能访问的路径
        if (path.contains("/system/admin/user/login")
                || path.contains("/system/admin/user/logout")
                || path.contains("/system/admin/kaptcha")) {
            LOG.info("不需要控台登录验证：{}", path);
            return chain.filter(exchange);
        }

        //用户网站-不需要登录就能访问的路径
        if (path.contains("/business/web/member/reset-password") ||
                path.contains("/file/web/get-auth") ||
                path.contains("/business/web/category") ||
                path.contains("/business/web/course") ||
                path.contains("/business/web/kaptcha") ||
                path.contains("/business/web/member/register") ||
                path.contains("/business/web/member/login") ||
                path.contains("/business/web/member/logout") ||
                path.contains("/business/web/member/is-mobile-exist") ||
                path.contains("/business/web/member-course") ||
                path.contains("/business/web/sms") ||
                path.contains("/business/web/discuss/detail") ||
                path.contains("/business/web/followees") ||
                path.contains("/business/web/followers") ||
                path.contains("/business/web/index") ||//所有帖子的页面
                path.contains("/business/web/search") ||
                path.contains("/business/web/profile") ||
                path.contains("/business/web/mypost") ||
                path.contains("/business/web/myreply")||
                path.contains("/file/web/oss-simple")
        ) {
            LOG.info("不需要用户端登录验证：{}", path);
            return chain.filter(exchange);
        }

        //用户网站-需要登录才能访问的路径
        if (path.contains("/business/web/comment/add") ||
                path.contains("/business/web/discuss/add") ||
                path.contains("/business/web/follow") ||
                path.contains("/business/web/unfollow") ||
                path.contains("/business/web/like") ||
                path.contains("/business/web/letter/list") ||
                path.contains("/business/web/letter/detail") ||
                path.contains("/business/web/letter/send") ||
                path.contains("/business/web/letter/delete") ||
                path.contains("/business/web/notice/list") ||
                path.contains("/business/web/notice/detail") ||
                path.contains("/business/web/member/headerUrl")||
                path.contains("/business/web/message/unreadcount")
        ) {
            //获取header的token参数
            String token = exchange.getRequest().getHeaders().getFirst("token");
            LOG.info("用户端登录验证开始，token：{}", token);
            if (token == null || token.isEmpty()) {
                LOG.info("token为空，请求被拦截");
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            }
            Object object = redisTemplate.opsForValue().get(token);
            if (object == null) {
                LOG.warn("token无效，请求被拦截");
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            } else {
                LOG.info("已登录：{}", object);


/*                // 增加权限校验，gateway里没有LoginUserDto，所以全部用JSON操作
                LOG.info("接口权限校验，请求地址：{}", path);
                LoginMemberDto loginMemberDto=JSON.parseObject(String.valueOf(object), LoginMemberDto.class);
                LOG.info("权限校验通过");
                // 在本次请求中持有用户
                Member member = CopyUtil.copy(loginMemberDto, Member.class);//todo 想要不对应的字段转为默认值，如果这个方法报错就手动转下。
                hostHolder.setMember(member);*/

/*                exchange.getRequest().getHeaders().set("token",token);
                exchange.getRequest().getHeaders().add("token",token);*/
                return chain.filter(exchange);
            }
        }

        //控台-需要登录才能访问的路径（控台的所有路径里去掉不需要登录的路径的剩下的所有路径）
        if (path.contains("/admin")) {
            //获取header的token参数
            String token = exchange.getRequest().getHeaders().getFirst("token");
            LOG.info("控台登录验证开始，token：{}", token);
            if (token == null || token.isEmpty()) {
                LOG.info("token为空，请求被拦截");
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            }
            Object object = redisTemplate.opsForValue().get(token);
            if (object == null) {
                LOG.warn("token无效，请求被拦截");
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            } else {
                LOG.info("已登录：{}", object);

                // 增加权限校验，gateway里没有LoginUserDto，所以全部用JSON操作
                LOG.info("接口权限校验，请求地址：{}", path);
                boolean exist = false;
                JSONObject loginUserDto = JSON.parseObject(String.valueOf(object));
                redisTemplate.opsForValue().set(token, JSON.toJSONString(loginUserDto), 3600, TimeUnit.SECONDS);
                JSONArray requests = loginUserDto.getJSONArray("requests");
                // 遍历所有【权限请求】，判断当前请求的地址是否在【权限请求】里
                for (int i = 0, l = requests.size(); i < l; i++) {
                    String request = (String) requests.get(i);
                    if (path.contains(request)) {
                        exist = true;
                        break;
                    }
                }
                if (exist) {
                    LOG.info("权限校验通过");

                } else {
                    LOG.warn("权限校验未通过");
                    exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                    return exchange.getResponse().setComplete();
                }

                return chain.filter(exchange);
            }
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 1;
    }
}
